package com.five.service.impl;

import com.five.api.AuthorServiceAPI;
import com.five.api.ReaderServiceAPI;
import com.five.api.UserServiceAPI;
import com.five.exception.BusinessException;
import com.five.jwt.JwtUtils;
import com.five.jwt.RsaUtils;
import com.five.mapper.LoginInfoMapper;
import com.five.pojo.*;
import com.five.service.LoginService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.net.URLDecoder;
import java.security.PrivateKey;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private LoginInfoMapper loginInfoMapper;
    @Autowired
    private AuthorServiceAPI authorServiceAPI;
    @Autowired
    private ReaderServiceAPI readerServiceAPI;
    @Autowired
    private UserServiceAPI userServiceAPI;


    /**
     * 登录
     */
    @Override
    @Transactional
    @GlobalTransactional
    public Map<String, Object> login(Map<String, Object> params) throws Exception {
        String username = (String) params.get("username");
        String password = (String) params.get("password");
        Integer type = (Integer) params.get("type");
        //1.非空校验
        if (StringUtils.isEmpty(username)) {
            throw new BusinessException("用户名不能为空");
        }
        if (StringUtils.isEmpty(password)) {
            throw new BusinessException("密码不能为空");
        }
        if (type == null) {
            throw new BusinessException("登录类型不能为空");
        }
        //2.通过用户名和类型从loginInfo表中查询登陆信息
        LoginInfo loginInfo = loginInfoMapper.queryByUsernameAndType(username, type);
        //3.是否能查到登陆信息
        if (Objects.isNull(loginInfo)) {
            loginInfo = new LoginInfo();
            if (type == 2) {
                Reader reader =  readerServiceAPI.queryByAccount(username).getData();
                if (Objects.isNull(reader)) {
                    throw new BusinessException("您未注册,请先注册后再来登陆");
                }
                BeanUtils.copyProperties(reader, loginInfo);
                loginInfo.setType(2);
                loginInfo.setLastLoginTime(new Date());
                loginInfo.setDisable(1);
                loginInfoMapper.insert(loginInfo);
                reader.setUpdate_time(LocalDateTime.now());
                reader.setLoginInfoId(loginInfo.getId());
                reader.setLast_login_time(LocalDateTime.now());
                readerServiceAPI.updateReader(reader);
            }else if (type == 1) {
                Author author = authorServiceAPI.queryByAccount(username).getData();
                if (Objects.isNull(author)) {
                    throw new BusinessException("您未注册,请先注册后再来登陆");
                }
                BeanUtils.copyProperties(author, loginInfo);
                loginInfo.setType(1);
                loginInfo.setLastLoginTime(new Date());
                loginInfo.setDisable(1);
                loginInfoMapper.insert(loginInfo);
                author.setUpdateTime(new Date());
                author.setLogininfoId(loginInfo.getId());
                author.setLastLoginTime(new Date());
                authorServiceAPI.updateAuthor(author);
            }else if(type == 0){
                User user = userServiceAPI.queryByAccount(username).getData();
                if (Objects.isNull(user)) {
                    throw new BusinessException("您未注册,请先注册后再来登陆");
                }
                BeanUtils.copyProperties(user, loginInfo);
                loginInfo.setType(1);
                loginInfo.setLastLoginTime(new Date());
                loginInfo.setDisable(1);
                loginInfoMapper.insert(loginInfo);
                user.setUpdateTime(new Date());
                user.setLoginInfoId(loginInfo.getId());
                user.setLastLoginTime(new Date());
                userServiceAPI.updateUser(user);
            }
        }
        //3.1如果有就将密码进行加盐加密后和查出来的密码比对是否一致
        String salt = loginInfo.getSalt();
        String dbPassword = loginInfo.getPassword();
        String md5Password = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        //3.2如果密码不一致,提示密码错误
        if (!Objects.equals(dbPassword, md5Password)) {
            throw new BusinessException("密码错误");
        }
        //4.如果密码一致,更新登陆信息的最后登陆时间
        loginInfo.setLastLoginTime(new Date());
        loginInfoMapper.update(loginInfo);

        HashMap<String, Object> map = new HashMap<>();
        //4.通过loginInfo的id查询后台用户对象
        if(type == 0){
            Long loginInfoId = loginInfo.getId();
            User user = userServiceAPI.queryByLoginInfoId(loginInfoId).getData();
            //5.通过员工id查询员工相应的权限和菜单
            Long userId = user.getId();
            List<String> permissions = null;
            List<Menu> menus = null;
            permissions = userServiceAPI.queryPermissionsByUserId(userId).getData();
            menus = userServiceAPI.queryMenusByUserId(userId).getData();
            map.put("permissions", permissions);
            map.put("menus", menus);
        }
        //6.生成jwtToken
        PrivateKey privateKey = RsaUtils.getPrivateKey(URLDecoder.decode(
                JwtUtils.class.getClassLoader().getResource("hrm_auth_rsa").getFile(), "UTF-8"));
        loginInfo.setPassword(null);
        loginInfo.setSalt(null);
        map.put("loginInfo", loginInfo);
        String token = JwtUtils.generateTokenExpireInSeconds(map, privateKey, 60*60*24);
        map.put("token", token);
        //7.将jwtToken返还给前端
        return map;
    }

}